# coding=utf-8
# 2020/4/1: 首个记录

import os
import sys
import datetime as dt
import bi_common as bi


# 样本读取
class SampleLoader:
    def __init__(self, dir):
        self.files = []
        self.protocols = {}
        self.offsets = {}
        self.pairs = {}
        abs_dir = os.path.join(sys.path[0], dir)
        for path in os.listdir(abs_dir):
            if path.endswith(".csv"):
                file = open(os.path.join(abs_dir, path))
                offset = SampleLoader.read_title(file)
                if offset is not None:
                    self.files.append(file)
                    self.protocols[file] = os.path.basename(path).split('.')[0]
                    self.offsets[file] = offset
                    self.pairs[file] = [None, None]

    def load(self, target, max_gap):
        table = {}
        for file in self.files:
            protocol = self.protocols[file]
            SampleLoader.update_pair(file, target, protocol, self.offsets[file], self.pairs[file])
            pair = self.pairs[file]
            if pair[0] is not None and pair[1] is not None:
                dt1 = target - pair[0].time
                dt2 = pair[1].time - target
                sample_pair = bi.agency.create_general_sample_pair()
                if dt1 > max_gap:
                    if dt2 <= max_gap:
                        sample_pair.sample1 = sample_pair.sample2 = pair[1]
                        sample_pair.weight1 = 1.0
                    else:
                        continue
                else:
                    if dt2 <= max_gap:
                        sample_pair.sample1 = pair[0]
                        sample_pair.sample2 = pair[1]
                        sample_pair.weight1 = dt2 / (dt1 + dt2)
                        sample_pair.weight2 = dt1 / (dt1 + dt2)
                    else:
                        sample_pair.sample1 = sample_pair.sample2 = pair[0]
                        sample_pair.weight1 = 1.0
                table[protocol] = sample_pair
        return table

    def close(self):
        for file in self.files:
            file.close()
        self.files = []
        self.protocols = {}
        self.offsets = {}
        self.pairs = {}

    @staticmethod
    def update_pair(file, target, protocol, offset, pair):
        while True:
            if pair[1] is not None and pair[1].time <= target:
                pair[0] = pair[1]
                pair[1] = None
            if pair[1] is None:
                pair[1] = SampleLoader.read_row(file, offset, protocol)
            if pair[1] is None or pair[1].time > target:
                break

    @staticmethod
    def read_row(file, offset, protocol):
        elems = file.readline().split(',')
        if len(elems) <= offset:
            return None
        sample = bi.agency.create_general_sample()
        sample.protocol = protocol
        sample.time = float(elems[offset])
        sample.values = []
        for i in range(offset + 1, len(elems)):
            elem = elems[i]
            if elem == 'na':
                sample.values.append(None)
            elif elem.isdecimal():
                sample.values.append(float(elem))
            else:
                sample.values.append(str(elem))
        sample.significant = len(sample.values)
        return sample

    @staticmethod
    def read_title(file):
        elems = file.readline().split(',')
        if 'Time' not in elems:
            elems = file.readline().split(',')
            if 'Time' not in elems:
                return None
        return elems.index('Time')


# 样本写入
class SampleWriter:
    def __init__(self, dir, sess):
        self.abs_dir = os.path.join(sys.path[0], dir)
        if not os.path.exists(self.abs_dir):
            os.mkdir(self.abs_dir)
        self.files = {}
        self.session = sess

    def write(self, sample):
        if sample is None or not hasattr(sample, 'protocol') or sample.protocol is None or len(sample.protocol) == 0:
            return
        protocol = str(sample.protocol)
        if protocol not in self.files:
            self.files[protocol] = open(os.path.join(self.abs_dir, protocol + '.csv'), 'w')
            self.files[protocol].write('Sample Table,v2\n')
            self.files[protocol].write('Session,Time\n')
        elems = list()
        elems.append(self.session.strftime('%Y%m%d-%H-%M-%S'))
        elems.append('%.6f' % sample.time)
        count = min(len(sample.values), sample.significant)
        for i in range(0, count):
            val = sample.values[i]
            if val is None:
                elems.append('na')
            else:
                elems.append(str(val))
        self.files[protocol].write(','.join(elems) + '\n')

    def close(self):
        for protocol in self.files:
            self.files[protocol].close()
        self.files = {}


# 独立运行
def run_standalone(input_dir, loop_func, interval=0.1, count=100, output_dir=None, start_func=None, end_func=None):
    bi.global_public_path = os.path.join(sys.path[0], 'global_public')
    bi.interval = interval
    now = dt.datetime.now()
    sess = dt.datetime(now.year, now.month, now.day, now.hour, now.minute, now.second, 0)
    loader = SampleLoader(input_dir)
    writer = None
    if output_dir is not None:
        writer = SampleWriter(output_dir, sess)
    if start_func is not None:
        start_func()
    for i in range(count):
        bi.time = (i + 1) * interval
        bi.session = sess
        bi.session_public_path = os.path.join(sys.path[0], 'session_public')
        bi.input_samples = loader.load(bi.time, 1)
        bi.output_samples.clear()
        loop_func()
        if writer is not None:
            for protocol in bi.output_samples:
                samples = bi.output_samples[protocol]
                if not isinstance(samples, list):
                    samples = [samples]
                for sample in samples:
                    writer.write(sample)
    if end_func is not None:
        end_func()
    loader.close()
    if writer is not None:
        writer.close()
